package com.fs.uc.core.behavior;

import com.fs.uc.base.domain.*;
import com.fs.uc.base.repo.AdditionalRoleRepository;
import com.fs.uc.base.repo.OrgRepository;
import com.fs.uc.base.repo.PersonRepository;
import com.fs.uc.base.repo.RoleRepository;
import com.fs.uc.core.CacheName;
import io.quarkus.arc.log.LoggerName;
import io.quarkus.cache.CacheInvalidate;
import io.quarkus.cache.CacheKey;
import io.quarkus.cache.CacheManager;
import org.jboss.logging.Logger;

import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.transaction.Transactional;

/**
 * @author 崔超
 * 2021/12/31
 */
@ApplicationScoped
@Transactional
class PersonBehaviorImpl implements PersonBehavior {
    @Inject
    PersonRepository personRepo;
    @Inject
    OrgRepository orgRepo;
    @Inject
    AdditionalRoleRepository additionalRoleRepo;
    @Inject
    RoleRepository roleRepo;
    @SuppressWarnings("CdiInjectionPointsInspection")
    @Inject
    CacheManager cacheManager;
    @LoggerName("PersonBehaviorImpl")
    Logger log;

    @Override
    public Person createByUserSelf(String openId, String phone, String name) {
        Person person = personRepo.findByPhone(phone);
        if (person == null) {
            person = new Person();
            person.phone = phone;
        }
        person.name = name;
        person.openid = openId;
        personRepo.persist(person);
        return person;
    }

    @Override
    public Person createByOrgAdmin(String phone, String name) {
        Person person = personRepo.findByPhone(phone);
        if (person != null) {
            return person;
        }
        person = new Person();
        person.name = name;
        person.phone = phone;
        personRepo.persist(person);
        return person;
    }

    @CacheInvalidate(cacheName = CacheName.PERSON_PERMISSION)
    @CacheInvalidate(cacheName = CacheName.PERSON_SUBJECT)
    @Override
    public Person switchCurrentOrg(@CacheKey Long personId, Long orgId) {
        Org org = orgRepo.getById(orgId);
        Person person = personRepo.getById(personId);

        boolean contains = person.orgs.contains(org);
        assert contains;

        person.currentOrg = org;
        return person;
    }

    @Override
    public void joinOrg(@CacheKey Long personId, Long orgId) {
        Org org = orgRepo.getById(orgId);
        Person person = personRepo.getById(personId);
        org.people.add(person);
        orgRepo.persist(org);

        if (person.currentOrg == null) {
            person.currentOrg = org;
            //清除缓存
            clearPersonCache(person);
        }
    }

    @Override
    public void leaveOrg(Long personId, Long orgId) {
        additionalRoleRepo.removeByOrgUser(orgId, personId);

        Org org = orgRepo.getById(orgId);
        Person person = personRepo.getById(personId);
        org.people.remove(person);

        if (person.currentOrg.id.equals(orgId)) {
            person.currentOrg = null;
            //清除缓存
            clearPersonCache(person);
        }

    }

    @Override
    public PersonIdentity getIdentity(Long personId) {
        Person person = personRepo.getById(personId);
        if (person.currentOrg == null) {
            return PersonIdentity.NormalPerson;
        }

        if (person.currentOrg.type == OrgType.Park) {
            if (person.manageOrgs.contains(person.currentOrg)) {
                return PersonIdentity.ParkAdmin;
            }
            return PersonIdentity.CustomUser;
        }

        if (person.manageOrgs.contains(person.currentOrg)) {
            return PersonIdentity.Boss;
        }
        return PersonIdentity.Employee;
    }

    private void clearPersonCache(Person person) {
        cacheManager.getCache(CacheName.PERSON_SUBJECT).ifPresent(cache -> cache.invalidate(person.id).subscribe().with(
                suc -> log.info(person.name + "清除人员身份缓存"),
                fail -> log.error("清除人员身份缓存异常：" + fail)
        ));
        cacheManager.getCache(CacheName.PERSON_PERMISSION).ifPresent(cache -> cache.invalidate(person.id).subscribe().with(
                suc -> log.info(person.name + "清除人员权限缓存"),
                fail -> log.error("清除人员权限缓存异常：" + fail)
        ));
    }
}
